import cmd
import sys
import os

# 使用base code 的common.py
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)
from base_code.common import *


class BDIAgent:
    """
    内部工作流程遵循“感知-决策-执行”循环。
    """

    def __init__(self):
        """
        初始化Agent。
        - Beliefs (信念): 存储数据的字典。
        - Plans (计划库): 将命令映射到具体的执行函数。
        """
        self.beliefs = {}
        self._plans = {
            'set': self._execute_set,
            'get': self._execute_get,
            'delete': self._execute_delete,
            'list': self._execute_list,
        }
        print("💡 BDIAgent 已初始化。内部循环已建立。")

    def run(self, command, raw_arg):
        """
        Agent的核心工作循环入口。
        接收原始输入，并依次执行感知、决策和执行。

        :param command: 命令名 (e.g., 'set')
        :param raw_arg: 未经处理的参数字符串 (e.g., 'name "John Doe"')
        :return: 执行结果的字符串。
        """
        # 1. 感知 (Perception): 解析原始输入，形成结构化愿望或发现错误
        perception_status, perception_result = self._perceive(command, raw_arg)

        if perception_status == 'error':
            return perception_result  # 如果感知阶段就发现错误，直接返回错误信息

        # 2. 决策 (Deliberation): 根据愿望选择一个计划（意图）
        desire = perception_result
        intention, plan_args = self._deliberate(desire)

        if not intention:
            return f"❌ 内部错误: Agent没有针对愿望 '{desire[0]}' 的计划。"

        # 3. 执行 (Execution): 执行选定的计划
        result = intention(*plan_args)

        return result

    def _perceive(self, command, raw_arg):
        """
        感知阶段：解析并验证输入，将其转换为结构化的“愿望”。
        所有输入校验逻辑都集中在此处。
        """
        arg = raw_arg.strip()

        if command == 'set':
            parts = arg.split(None, 1)
            if len(parts) < 2:
                return 'error', "❌ 错误: 'set' 命令需要一个键和一个值。\n   用法: set <key> <value>"
            key, value = parts
            return 'success', ('set', key, value)

        elif command in ['get', 'delete']:
            if not arg:
                return 'error', f"❌ 错误: '{command}' 命令需要一个键。\n   用法: {command} <key>"
            return 'success', (command, arg)

        elif command == 'list':
            return 'success', ('list',)

        else:
            # 这个分支理论上不会被触发，因为 cmd 模块会处理未知命令
            return 'error', f"❌ 内部错误: 感知到未知命令 '{command}'"

    def _deliberate(self, desire):
        """
        决策阶段：为给定的愿望选择一个计划，形成意图。
        """
        command = desire[0]
        args = desire[1:]

        # 从计划库中查找可以满足愿望的计划
        plan_to_execute = self._plans.get(command)

        # 返回意图（要执行的函数）和执行所需的参数
        return plan_to_execute, args

    # --- 执行 (Execution) 阶段：具体的计划实现 ---

    def _execute_set(self, key, value):
        """Plan for 'set' desire: 更新信念。"""
        self.beliefs[key] = value
        return f"✅ 成功: '{key}' 已设置为 '{value}'"

    def _execute_get(self, key):
        """Plan for 'get' desire: 查询信念。"""
        value = self.beliefs.get(key)
        if value is not None:
            return f"➡️ {key} = {value}"
        else:
            return f"🔍 未找到键: '{key}'"

    def _execute_delete(self, key):
        """Plan for 'delete' desire: 从信念中移除。"""
        if key in self.beliefs:
            del self.beliefs[key]
            return f"✅ 成功: 键 '{key}' 已被删除。"
        else:
            return f"🔍 未找到键: '{key}'"

    def _execute_list(self):
        """Plan for 'list' desire: 列出所有信念。"""
        if not self.beliefs:
            return "ℹ️  数据库为空。"

        lines = ["📋 当前存储的所有数据:"]
        max_key_len = max(len(k) for k in self.beliefs.keys()) if self.beliefs else 0
        for key, value in self.beliefs.items():
            lines.append(f"  - {key:<{max_key_len}} : {value}")
        return "\n".join(lines)


class SimpleAgentShell(cmd.Cmd):
    """
    一个极致简化的交互式Shell，作为纯粹的用户界面。
    它不包含任何业务逻辑或输入校验。
    """
    lines = [
        "     欢迎使用 SimpleAgent v1.0 (BDI循环版)",
        " ",
        "UI层完全简化，所有逻辑由Agent的P-D-A循环处理",
        " ",
        "set <key> <value>  - 设置一个键值对",
        "get <key>          - 获取一个键对应的值",
        "delete <key>       - 删除一个键值对",
        "list               - 列出所有存储的键值对",
        "help               - 显示帮助信息",
        "exit / quit        - 退出程序"
    ]
    intro = create_aligned_intro(lines)
    prompt = "agent> "

    def __init__(self):
        super().__init__()
        self.agent = BDIAgent()

    # --- do_* 方法被极致简化 ---
    # 它们的唯一职责是：将原始用户输入传递给Agent的循环入口。

    def do_set(self, arg):
        """将原始'set'输入传递给Agent。"""
        result = self.agent.run('set', arg)
        print(result)

    def do_get(self, arg):
        """将原始'get'输入传递给Agent。"""
        result = self.agent.run('get', arg)
        print(result)

    def do_delete(self, arg):
        """将原始'delete'输入传递给Agent。"""
        result = self.agent.run('delete', arg)
        print(result)

    def do_list(self, arg):
        """将原始'list'输入传递给Agent。"""
        result = self.agent.run('list', arg)
        print(result)

    # --- UI控制相关方法保持不变 ---

    def do_exit(self, arg):
        """退出交互式Shell。"""
        print("\n👋 感谢使用，再见！")
        return True

    def do_quit(self, arg):
        """`quit` 是 `exit` 的别名。"""
        return self.do_exit(arg)

    def do_EOF(self, arg):
        """处理 Ctrl+D (EOF)，实现优雅退出。"""
        print()
        return self.do_exit(arg)

    def help_set(self):
        print("\n".join([
            "命令: set <key> <value>",
            "功能: 创建或更新一个键值对。",
            "示例:",
            "  set name 'John Doe'",
            "  set age 30"
        ]))

    def default(self, line):
        """处理未知命令。"""
        print(f"❌ 未知命令: '{line}'。输入 'help' 查看可用命令列表。")


def main():
    """程序主入口。"""
    try:
        SimpleAgentShell().cmdloop()
    except KeyboardInterrupt:
        print("\n👋 检测到中断，程序退出。")
        sys.exit(0)

if __name__ == '__main__':
    main()